#!/usr/bin/env python

import os, sys
from liwe.module import LiweModule

class Banner ( LiweModule ):
	def __init__ ( self, liwe ):
		super ( Banner, self ).__init__ ( liwe, "banner2" )

		self.dbm = self.liwe.dbm
		self._dest_dir = 'site/banner/media'
		self._thumbs_dir = 'site/banner/thumbs'
		self.GRUPPO_FIELD = [ 'id', 'name' , 'created' ]
		self.TIPO_FIELD	= [ 'id', 'name', 'w', 'h', 'playtime','effect' ,  'created' ]
		self.BANNER_FIELD = [ 'id', 'id_gruppo', 'id_tipo', 'descr', 'data_on', 'data_off', 'peso', 'lnk', 'ext', 'kind', 'created' ]
		self.STAT_FIELD	= [ 'id', 'id_banner', 'created', 'cv' ]
		self.LIST_FIELD	= [ 'id_banner', 'descr','banner', 'id_gruppo', 'gruppo', 'id_tipo', 'tipo', 'data_on', 'data_off', 'peso', 'lnk', 'ext', 'created' ]
		self.SHOW_FIELD= [ 'id_banner', 'descr', 'banner', 'id_gruppo', 'id_tipo', 'lnk', 'ext' ]
		
		self.EFFECTSTR =  [ 'Swap', 'Crossfade', 'Push Right', 'Push Top', 'Push Left', 'Push Bottom' ] 


		self._init_dir ()

	def _init_dir ( self ):
		dir_tree =  os.path.join ( os.getcwd () , self._dest_dir )
		if not os.path.exists( dir_tree ):
			os.makedirs ( dir_tree )

	#{{{ GRUPPO FUNCTION
	#{{{def add_gruppo ( self, id, name ):
	#..function: Banner.add_gruppo ( id, name )
	#	Insert or Update in banner_gruppo table
	#	:param id:	ID's banner_gruppo table
	#	:param name:	Group name ( ex: customer )
	def add_gruppo ( self, id_gruppo, name ):
	
		vals = { 'name' : name, 'created' : '*NOW()' }
		
		if not id_gruppo:
			self.dbm.insert ( 'banner_gruppo', vals )
			id_gruppo = self.dbm.insert_id ()
			return id_gruppo

		self.dbm.update ( 'banner_gruppo', vals, 'id = %s' % id_gruppo )
		return id 
	#}}}
	#{{{def get_gruppo ( self, id, name ):
	#..function: Banner.get_gruppo ( id, name )
	#	return row of banner_gruppo table select for id or name
	#	:param id:	ID's banner_gruppo table
	#	:param name:	Name of gruppo
	def get_gruppo ( self, id_gruppo, name ):
		if not id_gruppo and not name : return []
		conds = []
		if id_gruppo : conds.append ( 'id = %s ' % id_gruppo )
		if name: conds.append ( "name = '%s'" % name )

		res = self.dbm.single_row ( 'banner_gruppo', self.GRUPPO_FIELD , 'and'.join ( conds ) )
	
		return res
	#}}}
	#{{{def list_gruppo ( self, name = '', quant = 10, start_point = 0, do_count = 0 ):
	#..function Banner.list_gruppo ( id, name )
	#	return rows of banner_gruppo table select for id or name
	#	:param id:	ID's banner_gruppo table
	#	:param name:	Name of gruppo
	#	:param quant: 	use in limit
        #       :param start_point:     start point for LIMIT condition
        #       :param do_count:        number of row for limit condition
	def list_gruppo ( self, name = '', quant = 10, start_point = 0, do_count = 0 ):
		conds = []
		if name: conds.append ( "name = '%s'" % name )

		tot_rows=0
		extras = ''

		if do_count:
			tot_rows = self.dbm.count ( 'banner_gruppo', '' )

		if quant != -1:
			extras = 'LIMIT %s, %s' % ( start_point, quant )

		rows = self.dbm.all_rows ( 'banner_gruppo',  self.GRUPPO_FIELD, extras = extras )
		if not rows: rows = []
		return { "rows" : rows, "tot_rows" : tot_rows }
	#}}}
	#{{{{def del_gruppo ( self, id_gruppo ):
	#..function Banner.del_gruppo ( id_gruppo )
	def del_gruppo ( self, id_gruppo ):

		ids = id_gruppo.split ( '|' )
		
		where = 'id_gruppo in ( %s )' % ','.join(ids)

		tot_banner = self.dbm.count ( 'banner','', where)
					
		if ( tot_banner ) : 
			self.liwe.set_error ( '1', 'Ci sono %s banner collegati a questo/i id' % tot_banner )
			return []

		where = 'id in ( %s )' % ','.join(ids)
		self.dbm.delete ( "banner_gruppo", where )

		return []
	#}}}
	#}}}
	#{{{ TIPO FUNCTION
	#{{{def add_tipo ( self, id, name, w ,h, playtime, effect ):
	#..function: Banner.add_tipo ( id, name )
	#	Insert or Update in banner_tipo table
	#	:param id:	ID's banner_tipo table
	#	:param name:	Group name ( ex: customer )
	def add_tipo ( self, id_tipo, name, w ,h, playtime, effect ):
	
		vals = { 'name' : name, 
			'w' : w,
			'h': h,
			'playtime' : playtime,
			'effect' : effect,
			'created' : '*NOW()' }
		
		if not id_tipo:
			self.dbm.insert ( 'banner_tipo', vals )
			id_tipo = self.dbm.insert_id ()
			return id_tipo

		self.dbm.update ( 'banner_tipo', vals, 'id = %s' % id_tipo )
		return id_tipo 

	#}}}
	#{{{def get_tipo ( self, id_tipo = 0, name = '' ):
	#..function: Banner.get_tipo ( id_tipo, name )
	#	return row of banner_tipo table select for id or name
	#	:param id_tipo:	ID's banner_tipo table
	#	:param name:	Name of tipo
	def get_tipo ( self, id_tipo = 0, name = '' ):
		#sys.stderr.write ( "\n\n\n************** ID TIPO: %s\n\n\n" % id_tipo )
		if not id_tipo and not name : return {}

		conds = []

		if id_tipo : conds.append ( 'id = %s ' % id_tipo )
		if name: conds.append ( "name = '%s'" % name )

		res = self.dbm.single_row ( 'banner_tipo', self.TIPO_FIELD , ' and '.join ( conds ) )
		if not res: return {}

		res [ 'effectstr' ] = self.EFFECTSTR [ res [ 'effect' ] ]

		return res
	#}}}
	#{{{def del_tipo ( self, id_tipo ):
	#..function Banner.del_tipo ( id_tipo )
	def del_tipo ( self, id_tipo ):

		ids = id_tipo.split ( '|' )
		
		where = 'id_tipo in ( %s )' % ','.join(ids)

		tot_banner = self.dbm.count ( 'banner','', where)
					
		if ( tot_banner ) : 
			self.liwe.set_error ( '1', 'Ci sono %s banner collegati a questo/i id' % tot_banner )
			return []

		where = 'id in ( %s )' % ','.join(ids)
		self.dbm.delete ( "banner_tipo", where )
		return [] 
	#}}}
	#{{{def list_tipo ( self, id = 0, name = '', quant=10, start_point = 0, do_count = 0 ):
	#..function Banner.list_tipo ( id, name )
	#	return rows of banner_tipo table select for id or name
	#	:param id:	ID's banner_tipo table
	#	:param name:	Name of tipo
	#	:param quant: 	use in limit
        #       :param start_point:     start point for LIMIT condition
        #       :param do_count:        number of row for limit condition
	def list_tipo ( self, id = 0, name = '', quant=10, start_point = 0, do_count = 0 ):
		conds = []
		if id : conds.append ( 'id = %s ' % id )
		if name: conds.append ( "name = '%s'" % name )

		tot_rows=0
		if do_count:
			tot_rows = self.dbm.count ( 'banner_tipo', '' )

		extras = ''
		if quant != -1:
			extras = 'LIMIT %s, %s' % ( start_point, quant )

		rows = self.dbm.all_rows ( 'banner_tipo',  self.TIPO_FIELD, extras = extras )
		if not rows: rows = []
		for row in rows:
			row [ 'effectstr' ] = self.EFFECTSTR [ row [ 'effect' ] ]
		return { "rows" : rows, "tot_rows" : tot_rows }
	#}}}
	#}}}
	#{{{ BANNER FUNCTION
	#{{{def add_banner ( self, id_banner, id_gruppo, id_tipo, descr, data_on, data_off, peso, lnk, file_obj=None, tags = '', date = '' ):
	#..function: Banner.add_banner ( id, name )
	#	Insert or Update in banner_banner table
	#	:param id:	ID's banner_banner table
	#	:param name:	Group name ( ex: customer )
	def add_banner ( self, id_banner, id_gruppo, id_tipo, descr, data_on, data_off, peso, lnk, file_obj=None, tags = '', date = '' ):
		if peso == 0: peso = 1

		vals = { 'id_gruppo' : id_gruppo,
			'id_tipo': id_tipo,
			'descr' : descr,
			'data_on' : data_on,
			'data_off' : data_off,
			'peso' : peso,
			'lnk' : lnk,
			'created' : '*NOW()' }

                if file_obj:
                        file_split = os.path.splitext ( file_obj [ 'filename' ] )
                        vals [ 'ext' ]       = file_split [ 1 ] [ 1: ]
                        vals [ 'kind' ]      = file_obj [ 'type' ]
	
		if not id_banner:
			self.dbm.insert ( 'banner', vals )
			id_banner = self.dbm.insert_id ()
			#Add file
			self._save_file ( id_banner, file_obj )
			vals [ 'id_banner' ] =  id_banner
		else:
			self.dbm.update ( 'banner', vals, 'id = %s' % id_banner )

		self.liwe.invoke ( "tags.admin.del_all_tags", id_obj = id_banner, id_site = self.site_id, module = "banner" )
		self.liwe.invoke ( "tags.ajax.tag_object", id_obj = id_banner, id_site = self.site_id, tags = tags, module = "banner" )

			
		self.dbm.delete ( "banner_date", "id_banner =  %s " % id_banner )
		if not date: return vals
		for dt in date.split ( "|" ):
			self.dbm.insert ( "banner_date", { 'id_banner' : id_banner, "data" : dt } ) 

		return vals
	#}}}
	#{{{def _save_file ( self, id_obj = '', file_obj = None ):
	#..function: Banner._save_file ( id_obj, file_obj )
	#	save file in banner directory
	#	:param id_obj:		ID's banner
	#	:param file_obj:	file to load
	def _save_file ( self, id_obj = '', file_obj = None ):
		if not id_obj or not file_obj : return

		split = os.path.splitext ( file_obj [ 'filename' ] )
		if split:
			ext = split [ 1 ] 
		else:
			ext = ""

		ext = ext.lower ()

		fil = file_obj [ 'file' ]
		fout_name = os.path.join ( self._dest_dir , "%s%s" % ( id_obj, ext ) )
		fout = open ( fout_name, "wb" )
		fout.write ( fil.read () )
		fout.close ()

		if ext in [ 'jpg', 'png', '.jpg', '.png' ]:
			from os3.utils.image_handler import ImageHandler
			ih = ImageHandler ()
			im = ih.load ( fout_name )
			im.toRGB ()
			#im.scale ( self.liwe.cfg.get ( "BANNER_THUMB_WIDTH", 150 ), self.liwe.cfg.get ( "BANNER_THUMB_HEIGHT", 100 ) )
			im.scale ( self.cfg.get ( "thumb.w", 150 ), self.cfg.get ( "thumb.h", 100 ) )
			im.save ( os.path.join ( self._thumbs_dir, "%s.jpg" % id_obj ) )
	#}}}
	#{{{def _remove_file ( self, id = '', ext = '' ):
	#..function:: Banner._remove_file
	#	Remove file from file system /site/banner/media
	#	:param id	ID's banner
	#	:param ext	file extension
	def _remove_file ( self, id_obj = '', ext = '' ):
		if not id_obj or not ext : return
		name =  "%s.%s" % ( id_obj, ext )
		path_name =  os.path.join ( self._dest_dir , name )
		try:
			os.remove ( path_name )
		except:
			pass

		try:
			os.remove ( os.path.join ( self._thumbs_dir, "%s.jpg" % id_obj ) )
		except:
			pass
		
	#}}}
	#{{{def get_banner ( self, id_banner ):
	#..function: Banner.get_banner ( id, name )
	#	return row of banner_banner table select for id or name
	#	:param id:	ID's banner_banner table
	#	:param name:	Name of banner
	def get_banner ( self, id_banner ):
		if not id_banner: return {}

		conds = []
		if id_banner: conds.append ( 'id = %s ' % id_banner )

		res = self.dbm.single_row ( 'banner', self.BANNER_FIELD, ' and '.join ( conds ) )
		if not res: return {}

		if res:
			tags = self.liwe.invoke ( "tags.ajax.tags_list", id_obj = res [ "id" ], id_site = self.site_id, module = 'banner' )
			res [ "tags" ] = tags [ "tags" ]
		

			date = []
			cur = self.dbm.select ( "banner_date", [ 'id_banner' , 'data' ] ,  "id_banner = %s" % id_banner )
			if cur:		
				for row in cur:
					
					date.append ( row [ 'data' ].strftime ( "%-d-%-m-%Y" ) )
				cur.close ()
		
				
			res [ 'date' ] = ( "|" ).join ( date )
		return res
	#}}}
	#{{{def del_banner ( self, ids = '' ):
	#..function:: Banner.delete ( ids )
	#	Remove row/s from banner table, remove imgage
	#	:param ids	ID's or IDs 
	def del_banner ( self, ids = '' ):
		
		if not ids: return

		id_lst = ids.split ( '|' )
		for id_banner in id_lst:
			banner = self.dbm.single_row ( 'banner', self.BANNER_FIELD, "id= %s" % id_banner )
			#remove imgages
			self._remove_file ( id_obj = id_banner , ext = banner[ 'ext' ] )

		self.dbm.delete ( "banner", "id in ( %s )  " % ','.join ( id_lst ) )
	#}}}
	#{{{def list_banner ( self, id_gruppo = 0, id_tipo = 0, data = 0, giorni = 0 , descr = '', quant=10, start_point = 0, do_count = False ):
	#..function Banner.list_banner ( id, name )
	#	return rows of banner_banner table select for id or name
	#	:param id:	ID's banner_banner table
	#	:param name:	Name of banner
	#	:param quant: 	use in limit
        #       :param start_point:     start point for LIMIT condition
        #       :param do_count:        number of row for limit condition

	def list_banner ( self, id_gruppo = 0, id_tipo = 0, data = 0, giorni = 0 , descr = '', quant=10, start_point = 0, do_count = False ):
		conds = []
		if id_gruppo : conds.append ( 'id_gruppo = %d ' % id_gruppo )
		if id_tipo : conds.append ( 'id_tipo = %d ' % id_tipo )
		
		if descr : conds.append ( "descr like '%%%s%%' " %  descr ) 
		if giorni:
			if not data:
				data = 'NOW()' 
			else:
				data = "'%s'" % data
				
			if giorni == -1:
				conds.append ( "data_off < %s" % data )
			else:
				conds.append ( "data_on < %s" % data )
				conds.append ( "DATE_ADD(%s, INTERVAL %d DAY) > data_off" % ( data, giorni ) )

		where = ' AND '.join ( conds )
                tot_rows = 0

                if do_count:
                        tot_rows = self.dbm.count ( 'banner', '', where ) 

		extras = ''
		if quant != -1:
			extras = 'LIMIT %s, %s' % ( start_point, quant )

                rows = self.dbm.all_rows ( 'banner_list',  self.LIST_FIELD, where, extras = extras, debug = self.debug () )

                if not rows: rows = []
                return { "rows" : rows, "tot_rows" : tot_rows }
	#}}}
	#}}}
	#{{{ FRONT-END
	#{{{def show_banner ( self, last_id = 0, id_tipo  = 0, tipo = '' ):
	def show_banner ( self, last_id = 0, id_tipo = 0, tipo = '' ):
		if not id_tipo and not tipo: 
			self.liwe.set_error ( '1', 'Wrong parameters id_tipo and/or tipo' )
			return {}

		conds = []
		exclude_ids = ''

		banner_key = "banner_ids%s_%s" % ( id_tipo, tipo )

		ids = self.liwe.pyhp.session.data.get ( banner_key, {} )
		if ids:
			exclude_ids = "id_banner NOT IN ( %s )" % ','.join ( ids.keys () ) 

		#conds.append  ( " data_on < NOW() and  NOW() < data_off " )
		conds.append  ( " NOW() BETWEEN data_on AND data_off " )
		if id_tipo : conds.append  ( "id_tipo = %s " % id_tipo )
		if tipo : conds.append ( "tipo = '%s'" % tipo )

		extras = "ORDER BY -LOG(1.0 - RAND()) / peso LIMIT 1"
		
		# Aggiungo in coda la condizione degli id_banner da escludere
		if exclude_ids: conds.append ( exclude_ids )
		rows = self.dbm.all_rows ( 'banner_list' , self.SHOW_FIELD, ' AND '.join ( conds ), extras = extras )
		if not rows and exclude_ids:
			ids = {}
			# Se non ho trovato niente, rimuovo la condizione di filtro su id_banner e rifaccio la query
			conds = conds [ : -1 ]
			# fix by keeper: tolgo sempre l'ultimo banner visto altrimenti si blocca
			conds.append ( "id_banner != %s" % last_id )
			rows = self.dbm.all_rows ( 'banner_list' , self.SHOW_FIELD, ' AND '.join ( conds ), extras = extras )

		if not rows:
			self.liwe.set_error ( '2', 'No record for %s %s' % ( id_tipo, tipo ) )
			return {}

		res = rows [ 0 ]

		ids [ str ( res [ 'id_banner' ] ) ] = 1
		#self.liwe.pyhp.session.data [ banner_key ] = ids

		self.liwe.invoke ( "stats.ajax.log", module = 'banner' , id_ref = res [ 'id_banner' ] ) 
		return res
	#}}}
	#}}}

	def load_banner ( self, id_tipo = 0, tipo = '', tmpl = '' ):
		from os3.utils.utils import tmpnam

		id_tipo = int ( id_tipo )
		tipo = self.get_tipo ( id_tipo = id_tipo, name = tipo )

		if not tmpl:
			tmpl = 'bn-box-img'

		if not tipo:
			html = "Banner type not found: %s / %s" % ( id_tipo, tipo )

		bn = self.show_banner ( id_tipo = tipo.get ( "id" ) )

		if not bn:
			html = "Banner empty for type %s" % tipo
			return  { 'html' : html, 'name' : '', 'tipo' : tipo }

		#sys.stderr.write ( "BN: %s, tipo: %s" % ( bn, tipo ) )
		bn [ 'w' ] = tipo.get ( 'w', 0 )
		bn [ 'h' ] = tipo.get ( 'h', 0 ) 

		if bn [ 'ext' ] == 'swf':

			bn [ 'swf' ] = '/site/banner/media/%s.swf' % bn [ 'id_banner' ]
			tpl = self.templates [ 'bn-box-flash' ]

		else:
			tpl = self.templates [ tmpl ]

		tipo [ '_banner' ] = tpl % bn
		html = self.templates [ 'bn-box' ] % tipo

		name = tmpnam ( "banner2-", ext = "div" )
		html = '<div id="%s">%s</div>' % ( name, html )

		return  { 'html' : html, 'tipo' : tipo, 'name' : name }
